/*
 ============================================================================
 Name        : ADLgettemp.c
 Author      : Vasily Tereshko <tolmi@end.kiev.ua>
 Version     : 0.01
 Copyright   : Copyleft 2010
 Description : Get temperature and FAN speed from ATI cards by ADL library
 ============================================================================
 */
#define __stdcall
#include "adl_sdk.h"
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
// Definitions of the used function pointers.
typedef int (*ADL_MAIN_CONTROL_CREATE)(ADL_MAIN_MALLOC_CALLBACK, int);
typedef int (*ADL_MAIN_CONTROL_DESTROY)();
typedef int (*ADL_ADAPTER_NUMBEROFADAPTERS_GET)(int*);
typedef int (*ADL_OVERDRIVE5_CURRENTACTIVITY_GET) (int , ADLPMActivity *);
typedef int (*ADL_OVERDRIVE5_TEMPERATURE_GET)(int, int,  ADLTemperature *);
typedef int (*ADL_OVERDRIVE5_FANSPEED_GET)(int,int,ADLFanSpeedValue *);

// Memory allocation function
void* ADL_Main_Memory_Alloc(int iSize) {
	void* lpBuffer = malloc(iSize);
	return lpBuffer;
}

// Optional Memory de-allocation function
void ADL_Main_Memory_Free(void** lpBuffer) {
	if (NULL != *lpBuffer) {
		free(*lpBuffer);
		*lpBuffer = NULL;
	}
}

int main(void) {
	void *hDLL; // Handle to .so library
	int iNumberAdapters = 0;
	int i;
	float tmp,tmp2;
	char *s;
	ADL_MAIN_CONTROL_CREATE ADL_Main_Control_Create;
	ADL_MAIN_CONTROL_DESTROY ADL_Main_Control_Destroy;
	ADL_ADAPTER_NUMBEROFADAPTERS_GET ADL_Adapter_NumberOfAdapters_Get;
	ADL_OVERDRIVE5_CURRENTACTIVITY_GET 	ADL_Overdrive5_CurrentActivity_Get;
	ADL_OVERDRIVE5_TEMPERATURE_GET   ADL_Overdrive5_Temperature_Get;
	ADL_OVERDRIVE5_FANSPEED_GET   ADL_Overdrive5_FanSpeed_Get;
	ADLTemperature ADLTemp;
	ADLPMActivity ADLactinfo;
	ADLFanSpeedValue ADLfan;

	/*****************/
	ADLTemp.iSize=sizeof(ADLTemp);
	ADLactinfo.iSize=sizeof(ADLactinfo);
	ADLfan.iSize=sizeof(ADLfan);
	hDLL = dlopen("libatiadlxx.so", RTLD_LAZY | RTLD_GLOBAL);
	if (NULL == hDLL) {
		printf("ADL library not found!\n");
		return 0;
	}
	ADL_Main_Control_Create = (ADL_MAIN_CONTROL_CREATE) dlsym(hDLL,
			"ADL_Main_Control_Create");
	ADL_Main_Control_Destroy = (ADL_MAIN_CONTROL_DESTROY) dlsym(hDLL,
			"ADL_Main_Control_Destroy");
	ADL_Adapter_NumberOfAdapters_Get
			= (ADL_ADAPTER_NUMBEROFADAPTERS_GET) dlsym(hDLL,
					"ADL_Adapter_NumberOfAdapters_Get");
	ADL_Overdrive5_Temperature_Get = (ADL_OVERDRIVE5_TEMPERATURE_GET)dlsym(hDLL,"ADL_Overdrive5_Temperature_Get");
	ADL_Overdrive5_CurrentActivity_Get = (ADL_OVERDRIVE5_CURRENTACTIVITY_GET)dlsym(hDLL,"ADL_Overdrive5_CurrentActivity_Get");
	ADL_Overdrive5_FanSpeed_Get = (ADL_OVERDRIVE5_FANSPEED_GET)dlsym(hDLL,"ADL_Overdrive5_FanSpeed_Get");
	// Initialize ADL. The second parameter is 1, which means:
	// retrieve adapter information only for adapters that are physically present and enabled in the system
	if (ADL_OK != ADL_Main_Control_Create(ADL_Main_Memory_Alloc, 1)) {
		printf("ADL Initialization Error!\n");
		return 0;
	}
	// Obtain the number of adapters for the system
	if (ADL_OK != ADL_Adapter_NumberOfAdapters_Get(&iNumberAdapters)) {
		printf("Cannot get the number of adapters!\n");
		return 0;
	}
	for (i = 0; i < iNumberAdapters; i++) {
		printf("\nAdapter %d", i);
		if (ADL_OK != ADL_Overdrive5_CurrentActivity_Get(i,&ADLactinfo)){
			printf("Cannot get the activity info of adapter!\n");
		}
		else{
			tmp=ADLactinfo.iEngineClock/100.0;
			tmp2=ADLactinfo.iMemoryClock/100.0;
			printf("\n\tEngine Frequency %6.0f MHz\n\tMemory Frequency %6.0f MHz",tmp,tmp2);
			tmp=ADLactinfo.iCurrentBusSpeed/10.0;
			tmp2=ADLactinfo.iActivityPercent;
			printf("\n\tBus Speed %dx%.0f MHz\n\tCurrent Activity %6.0f %%",ADLactinfo.iCurrentBusLanes, tmp,tmp2);
			tmp=ADLactinfo.iVddc/1000.0;
			printf("\n\tVddc %6.3f V\n\tPerformance Level %d ",tmp,ADLactinfo.iCurrentPerformanceLevel);
		}
		if (ADL_OK != ADL_Overdrive5_Temperature_Get(i,0,&ADLTemp)){
			printf("Cannot get the temperature of adapter!\n");
		}
		else {
		    tmp=ADLTemp.iTemperature/1000.0;
		    printf("\n\tTemperature = %5.1f \302\260C",tmp);
		}
		if (ADL_OK != ADL_Overdrive5_FanSpeed_Get(i,0,&ADLfan)){
			printf("Cannot get the Fan speed of adapter!\n");
		}
		else {
		    tmp=ADLfan.iFanSpeed;
		    if (ADLfan.iSpeedType==2){s="RPM";}else{s="%";}
		    printf("\n\tFan Speed = %5.1f %s",tmp,s);
		}
	}
	ADL_Main_Control_Destroy();
	dlclose(hDLL);
	return EXIT_SUCCESS;
}
